package org.elzat.healthboxgatewayapp.security;

import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.elzat.healthboxgatewayapp.config.HealthBoxJwtConfig;
import org.springframework.http.HttpHeaders;
import org.springframework.security.authentication.ReactiveAuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.context.SecurityContext;
import org.springframework.security.core.context.SecurityContextImpl;
import org.springframework.security.web.server.context.ServerSecurityContextRepository;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

@Component
@AllArgsConstructor
@Slf4j
public class HealthBoxSecurityContextRepository implements ServerSecurityContextRepository {

    private final ReactiveAuthenticationManager authenticationManager;
    private final HealthBoxJwtConfig healthBoxJwtConfig;

    @Override
    public Mono<Void> save(ServerWebExchange exchange, SecurityContext context) {
        throw new UnsupportedOperationException("not supported");
    }

    @Override
    public Mono<SecurityContext> load(ServerWebExchange exchange) {
        String token = exchange.getRequest().getHeaders().getFirst(HttpHeaders.AUTHORIZATION);
        return Mono.justOrEmpty(token)
                .filter(authHeader -> authHeader.startsWith(healthBoxJwtConfig.getTokenPrefix()))
                .switchIfEmpty(Mono.empty())
                .flatMap(authHeader -> {
                    String authToken = authHeader
                            .replaceFirst(healthBoxJwtConfig.getTokenPrefix(), "");
                    UsernamePasswordAuthenticationToken auth =
                            new UsernamePasswordAuthenticationToken(authToken, authToken);
                    return this.authenticationManager
                            .authenticate(auth)
                            .map(SecurityContextImpl::new);
                });
    }
}
